﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using System.Data;
using Ais3.DBS.General.BE;
using Ais3.DBS.General.BE.Enum;
//using System.Data.OleDb;

namespace Ais3.DBS
{
	/// <summary>
	/// Базовый класс для доступа к данным
	/// </summary>
	public class BaseDA : IDisposable
	{
		OracleConnection _conn;
		public BaseDA()
		{
			string constr = @"DATA SOURCE=DBS_MON;PERSIST SECURITY INFO=True;USER ID=DBS$MON;Password=DBS$MON";
			_conn = new OracleConnection(constr);
			_conn.Open();
		}

		void IDisposable.Dispose()
		{
			if (_conn != null)
			{
				_conn.Dispose();
				_conn = null;
			}
		}

		/// <summary>
		/// Тип таймаута команды (значения задаются конфиг файлом, берется с сервера конфигурации)
		/// </summary>
		public enum CommandTimeoutType
		{
			/// <summary>
			/// По умолчанию
			/// </summary>
			Default,

			/// <summary>
			/// Короткий
			/// </summary>
			Short,

			/// <summary>
			/// Безлимитный
			/// </summary>
			Unlimited
		}

		/// <summary>
		/// Возвращает таймаут нужного типа для команды
		/// </summary>
		/// <param name="timeoutType">Тип таймаута команды</param>
		/// <returns></returns>
		protected int GetTimeout(CommandTimeoutType timeoutType)
		{
			return 0;
		}
		protected const string DbSchemaName0508 = "dbs$mon.";
		/// <summary>
		/// Выполняет данную SQL-команду получения данных
		/// </summary>
		/// <param name="command">SQL-команда</param>
		/// <param name="dalFunction">Функция, обрабатыющая результат выполнения запроса к БД</param>
		protected void ExecuteReaderCommand(OracleCommand command, Action<OracleDataReader> dalFunction)
		{
			using (command)
			{
				command.BindByName = true;
				if (command.CommandType == CommandType.StoredProcedure &&
					!command.Parameters.Contains("vp_cursor"))
					AddCursorParameter(command);

				command.Connection = _conn;

				using (OracleDataReader dalResult = command.ExecuteReader())
				{
					dalFunction(dalResult);
				}
			}
		}
		/// <summary>
		/// Добавляет возвращаемый параметр - курсор в вызов хранимой процедуры.
		/// Для команд типа 'StoredProcedure' курсор добавляется автоматически при вызове метода ExecuteReaderCommand!
		/// </summary>
		/// <param name="command">Sql-команда</param>
		protected void AddCursorParameter(OracleCommand command)
		{
			AddCursorParameter(command, "vp_cursor");
		}

		/// <summary>
		/// Добавляет возвращаемый параметр - курсор в вызов хранимой процедуры.
		/// </summary>
		/// <param name="command">SQL-команда</param>
		/// <param name="cursorParName">Имя параметра-курсора</param>
		protected void AddCursorParameter(OracleCommand command, string cursorParName)
		{
			OracleParameter outParameter = new OracleParameter();
			outParameter.Direction = ParameterDirection.Output;
			outParameter.ParameterName = cursorParName;
			outParameter.OracleDbType = OracleDbType.RefCursor;
			command.Parameters.Add(outParameter);
		}
		#region Вспомогательные методы для работы с DBNull-значениями

		protected static T? DBNullToValue<T>(object o) where T : struct
		{
			if (o is DBNull)
				return null;
			else
				return (T)Convert.ChangeType(o, typeof(T));
		}

		protected static T DBNullToObject<T>(object o) where T : class
		{
			return (T)(o is DBNull ? null : o);
		}

		protected static object ValueToDBNull<T>(T? x) where T : struct
		{
			return (x.HasValue ? x.Value : (object)DBNull.Value);
		}

		protected static object ObjectToDBNull<T>(T x) where T : class
		{
			if (x != null)
				return x;
			else
				return (object)DBNull.Value;
		}

		#endregion
		/// <summary>
		/// Получает данные об утверждении из стандартных полей
		/// </summary>
		/// <param name="dataReader">Ридер БД</param>
		/// <returns></returns>
		protected DocApprovingInfo FillApprovingInfo(OracleDataReader dataReader)
		{
			DocApprovingInfo result = new DocApprovingInfo();

			result.ApprovingState = (dataReader["approving_state"] == DBNull.Value)
				? 0 : (ApprovingStateType)(short)dataReader["approving_state"];

			result.ApprovingDate = DBNullToValue<DateTime>(dataReader["approving_date"]);

			result.ApproverUser.Fio = DBNullToObject<String>(dataReader["approver_user_fio"]);
			result.ApproverUser.Post = DBNullToObject<String>(dataReader["approver_user_post"]);
			result.ApproverUser.Rank = DBNullToObject<String>(dataReader["approver_user_rank"]);

			return result;
		}

		/// <summary>
		/// Получает данные о подписании из стандартных полей
		/// </summary>
		/// <param name="dataReader">Ридер БД</param>
		/// <returns></returns>
		protected DocSigningInfo FillSigningInfo(OracleDataReader dataReader)
		{
			DocSigningInfo result = new DocSigningInfo();

			result.SigningState = (dataReader["signing_state"] == DBNull.Value)
				? 0 : (SigningStateType)(short)dataReader["signing_state"];

			result.SigningDate = DBNullToValue<DateTime>(dataReader["signing_date"]);

			result.SignerUser.Fio = DBNullToObject<String>(dataReader["signer_user_fio"]);
			result.SignerUser.Post = DBNullToObject<String>(dataReader["signer_user_post"]);
			result.SignerUser.Rank = DBNullToObject<String>(dataReader["signer_user_rank"]);

			return result;
		}
	}
}
